{literal}
<h2>Listeners</h2>

Listeners can be omitted to class or to property.<br>
Listeners omitted to class will always be called. For example beforeSave listener will be always called. 
It does not matter which property was changed and will be saved.<br>
It is different with property listeners. Property listeners will only be called when event is happening with that property.

<h2>List of basic listeners</h2>
<table cellspacing="0" cellpadding="8" border="1">
	<colgroup>
		<col width="130"></col>
		<col width="100"></col>
	</colgroup>	
	<tr>
		<td colspan="3"><b>INSERT</b> On Insert record object to db</td>
	</tr>
	<tr>
		<td>beforeInsert</td>
		<td>class,property</td>
		<td>
			Will be called before actual insert query to database is made
		</td>
	</tr>
	<tr>
		<td>afterInsert</td>
		<td>class,property</td>
		<td>
			Will be called after query is inserted into database. Object has id when this listener is called!
		</td>
	</tr>
	<tr>
		<td colspan="3"><b>UPDATE</b> On update record object (Already inserted into db)</td>
	</tr>
	<tr>
		<td>beforeUpdate</td>
		<td>class,property</td>
		<td></td>
	</tr>
	<tr>
		<td>afterUpdate</td>
		<td>class,property</td>
		<td></td>
	</tr>
	<tr>
		<td colspan="3"><b>SAVE</b> On insert or update record object </td>
	</tr>
	<tr>
		<td>beforeSave</td>
		<td>class,property</td>
		<td>Object might not have ID! Be careful with this!</td>
	</tr>
	<tr>
		<td>afterSave</td>
		<td>class,property</td>
		<td></td>
	</tr>
	<tr>
		<td colspan="3"><b>DELETE</b> On delete record object</td>
	</tr>
	<tr>
		<td>beforeDelete</td>
		<td>class,property</td>
		<td></td>
	</tr>
	<tr>
		<td>afterDelete</td>
		<td>class,property</td>
		<td>Object doesn't have ID anymore. </td>
	</tr>
	<tr>
		<td colspan="3"><b>SET</b> On update property value</td>
	</tr>
	<tr>
		<td>beforeValidate</td>
		<td>property</td>
		<td>This will be called before new value is being validated. Very useful to change the value before it will be "officially" validated.</td>
	</tr>
	<tr>
		<td colspan="3">
<pre class="code">
&lt;?php
/**
* @orm listener beforeInsert beforeInsertMethod
* @orm listener afterInsert afterInsertMethod
*/
class MyClass extends DomArObject {
	/**
	* @orm int(10)
	* @orm listener beforeValidate beforeValidate
	*/
	public $someProperty;
	
	public function beforeValidate( &$value ) {
		if( $value == 'ten' )
			$value = 10;
		else if( $value == 'eleven' )
			$value = 11;
		else;
			// do nothing. If its Int then it will pass validation. 
	}
}
?&gt;
</pre>
		</td>
	</tr>
	<tr>
		<td>beforeSet</td>
		<td>property</td>
		<td>This will be called after new value is validated, but old value can still be accessed through object</td>
	</tr>
	<tr>
		<td colspan="3">
<pre class="code">
&lt;?php
/**
* @orm listener beforeInsert beforeInsertMethod
* @orm listener afterInsert afterInsertMethod
*/
class MyClass extends DomArObject {
	/**
	* @orm int(10)
	* @orm listener beforeSet beforeSetMeth
	*/
	public $someProperty;
	
	public function beforeSetMeth( &$value ) {
		echo 'Old value: '.$this->someProperty.'&lt;br&gt;';
		echo 'New value: '.$value.'&lt;br&gt;';
	}
}
?&gt;
</pre>
		</td>
	</tr>
	<tr>
		<td>afterSet</td>
		<td>property</td>
		<td>This will be called after new value is omitted to object. Old value cannot be accessed anymore. </td>
	</tr>
</table>

<h2>Basic sample</h2>
<pre class="code">
&lt;?php
/**
* @orm listener beforeInsert beforeInsertMethod
* @orm listener afterInsert afterInsertMethod
*/
class MyClass extends DomArObject {
	/**
	* @orm text
	* @orm listener beforeInsert beforeInsertSomePropertyMethod
	* @orm listener afterInsert afterInsertSomePropertyMethod
	*/
	public $someProperty;
	
	public function beforeInsertMethod() {}
	
	public function beforeInsertMethod() {}
	
	public function beforeInsertSomePropertyMethod() {}
	
	public function afterInsertSomePropertyMethod() {}
	
}
?&gt;
</pre>

<h2>1:n, n:m listeners</h2>

<table width="90%" cellspacing="0" cellpadding="5" border="1">
	<colgroup>
		<col width="130"></col>
		<col width="100"></col>
	</colgroup>
	<tr>
		<td colspan="3"><b>ADD</b> When child object is added to list</td>
	</tr>
	<tr>
		<td>beforeAdd</td>
		<td>property</td>
		<td></td>
	</tr>
	<tr>
		<td>afterAdd</td>
		<td>property</td>
		<td></td>
	</tr>
	<tr>
		<td colspan="3"><b>REMOVE</b> When child object is removed from list</td>
	</tr>
	<tr>
		<td>beforeRemove</td>
		<td>property</td>
		<td></td>
	</tr>
	<tr>
		<td>afterRemove</td>
		<td>property</td>
		<td></td>
	</tr>
</table>
<pre class="code">
&lt;?php
class MyClass extends DomArObject {
	/**
	* @orm has children SomeClass inverse somewhere
	* @orm listener beforeAdd beforeAddMethod
	* @orm listener afterAdd afterAddMethod
	* @orm listener beforeRemove beforeRemoveMethod
	* @orm listener afterRemove afterRemoveMethod
	*/
	public $someProperty;
	
	public function beforeAdd( SomeClass $item ) {}
	
	public function afterAdd( SomeClass $item ) {}
	
	public function beforeRemove( SomeClass $item ) {}
	
	public function afterRemove( SomeClass $item ) {}
	
}
?&gt;
</pre>


<h2>Song/Artist sample</h2>
<pre class="code">
&lt;?php
class Song extends DomArObject {
	/**
	* @orm has child Artist inverse songs
	* @orm listener beforeValidate beforeValidateArtist
	*/
	public $artist;
	
	public function beforeValidateArtist( &$value ) {
		if( is_string($value;) ) {
		
			$dbArtist = Artist::query()->where("t.name LIKE '".addslashes( $value )."'")->limit(1)->commit();
			if( is_object($dbArtist) ) {
				$value = $dbArtist;
			
			} else {
				$artist = new  Artist();
				$artist->name = $value;
				$value = $artist;
			}
		}
	}
}
class Artist extends DomArObject {
	/**
	* @orm has parents Song inverse artist
	*/
	public $songs;
	/**
	* @orm char(100)
	*/
	public $name;
}

// using
$song = new Song();
$song->artist = 'Some wicked cool artist name';
// new Artist object was automatically created!
echo get_class($song->artist).' - '.$song->artist->name; // echoes "Artist - Some wicked cool artist name"

$song->save(); // saves Song and new Artist to database.

// you can also do this
$artist = new Artist();
$artist->name = 'Another artist';
$song->artist = $artist;
echo get_class($song->artist).' - '.$song->artist->name; // echoes "Artist - Another artist"

?&gt;
</pre>
{/literal}